package com.example.for_screen_push;

import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.projection.MediaProjection;
import android.os.Environment;
import android.util.Log;
import android.view.Surface;

import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.ByteBuffer;

public class CodecLiveH265 extends Thread{
    MediaCodec mediaCodec;
    MediaProjection mediaProjection;
    VirtualDisplay virtualDisplay;
    int width = 720,height = 1280;

    public static final int NAL_I = 19;
    public static final int NAL_VPS = 32;
    private byte[] vps_sps_pps_buf;

    public CodecLiveH265(MediaProjection mediaProjection) {
        this.mediaProjection = mediaProjection;
    }


    public void startLive(){
        try {
//            MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_HEVC,width,height);
            MediaFormat format = MediaFormat.createVideoFormat("video/hevc",width,height);
            format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
            format.setInteger(MediaFormat.KEY_BIT_RATE, width * height);
            format.setInteger(MediaFormat.KEY_FRAME_RATE, 20);
            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
//            mediaCodec = MediaCodec.createEncoderByType("video/hevc");
            mediaCodec = MediaCodec.createEncoderByType("video/hevc");
            mediaCodec.configure(format, null,null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            Surface surface = mediaCodec.createInputSurface();
            virtualDisplay = mediaProjection.createVirtualDisplay(
                    "-display",
                    width,height,1,
                    DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,surface,
                    null, null);

        } catch (Exception e) {
            e.printStackTrace();
        }
       start();
    }

    @Override
    public void run() {
        super.run();
        mediaCodec.start();
        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        while (true){
            int outputBufferId = mediaCodec.dequeueOutputBuffer(bufferInfo,10000);
            if (outputBufferId >= 0){
                ByteBuffer byteBuffer = mediaCodec.getOutputBuffer(outputBufferId);
//                byte[] outData = new byte[bufferInfo.size];
//                byteBuffer.get(outData);
////                WriteBytes(outData);
//                writeContent(outData);
                dealFrame(byteBuffer,bufferInfo);
                mediaCodec.releaseOutputBuffer(outputBufferId,false);
            }
        }
    }

    private void dealFrame(ByteBuffer byteBuffer, MediaCodec.BufferInfo bufferInfo) {
        int offset = 4;
        if (byteBuffer.get(2) == 0x01){
            offset = 3;
        }
        int type = byteBuffer.get(offset & 0x7E) >> 1;
        if (type == NAL_VPS){
            vps_sps_pps_buf = new byte[bufferInfo.size];
            byteBuffer.get(vps_sps_pps_buf);
        }
    }
    public String writeContent(byte[] array){
        char[] HEX_CHAR_TABLE = {
                '0','1','2','3','4','5','6','7','8','9',
        };
        StringBuilder sb = new StringBuilder();
        for (byte b : array){
            sb.append(HEX_CHAR_TABLE[(b & 0xf0) >> 4]);
            sb.append(HEX_CHAR_TABLE[(b & 0xf0)]);
        }
        Log.e("writeContent",sb.toString());
        FileWriter writer = null;
        try {
            writer = new FileWriter(Environment.getExternalStorageDirectory()+"/codecH265.txt",true);
            writer.write(sb.toString());
            writer.write('\n');
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (writer!=null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
    private void WriteBytes(byte[] outData) {
        FileOutputStream write = null;

        try {
            write = new FileOutputStream(Environment.getExternalStorageDirectory()+"/codec.h265",true);
            write.write(outData);
            write.write('\n');

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (write!=null) {
                    write.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
}
